﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.IO;
using System.IO.IsolatedStorage;
using System.Linq;
using System.Windows;
using System.Windows.Controls;
using System.Xml.Linq;
using SLBIARVerify.ClassLib;

namespace SLBIARVerify
{
    public partial class BIARComparison : Page, INotifyPropertyChanged
    {
        #region INotifyPropertyChanged Members

        public event PropertyChangedEventHandler PropertyChanged;

        protected void NotifyPropertyChanged(String propertyName)
        {
            if (PropertyChanged != null)
                PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
        }
        #endregion

        string targetXmlName = "targetBusinessObjects.xml";

        string targetBIARFileName = "TargetBusinessObjects.biar";

        public string TargetBIARFileName
        {
            get { return targetBIARFileName; }
            set
            {
                targetBIARFileName = value;
                NotifyPropertyChanged("TargetBIARFileName");
            }
        }
        string sourceBIARFileName = "SourceBusinessObjects.biar";

        public string SourceBIARFileName
        {
            get { return sourceBIARFileName; }
            set
            {
                sourceBIARFileName = value;
                NotifyPropertyChanged("SourceBIARFileName");
            }
        }

        string sourceXmlName = "businessobjects.xml";

        int newObjectNumber;

        public int NewObjectNumber
        {
            get { return newObjectNumber; }
            set
            {
                newObjectNumber = value;
                NotifyPropertyChanged("NewObjectNumber");
            }
        }
        int onlyInDestinationNumber;

        public int OnlyInDestinationNumber
        {
            get { return onlyInDestinationNumber; }
            set
            {
                onlyInDestinationNumber = value;
                NotifyPropertyChanged("OnlyInDestinationNumber");
            }
        }
        int sameNameDiffIDNumber;

        public int SameNameDiffIDNumber
        {
            get { return sameNameDiffIDNumber; }
            set
            {
                sameNameDiffIDNumber = value;
                NotifyPropertyChanged("SameNameDiffIDNumber");
            }
        }
        int sameIDDiffNameNumber;

        public int SameIDDiffNameNumber
        {
            get { return sameIDDiffNameNumber; }
            set
            {
                sameIDDiffNameNumber = value;
                NotifyPropertyChanged("SameIDDiffNameNumber");
            }
        }

        public BIARComparison()
        {
            InitializeComponent();
        }

        // Executes when the user navigates to this page.
        private void button1_Click(object sender, RoutedEventArgs e)
        {
            this.NavigationService.Navigate(new Uri("", UriKind.Relative));
        }

        private void btSelectAnotherBIAR_Click(object sender, RoutedEventArgs e)
        {
            //    OpenFileDialog dlg = new OpenFileDialog();
            //    dlg.Filter = "BIAR files|*.biar";
            //    if (dlg.ShowDialog() == true)
            //    {

            //        if (!dlg.File.Name.ToLower().EndsWith("biar"))
            //        {
            //            MessageBox.Show("I can only accept BIAR file.", "Error", MessageBoxButton.OK);
            //        }
            //        else
            //        {
            //            FileInfo fi = dlg.File;
            //            TargetBIARFileName = fi.Name;
            //            using (IsolatedStorageFile isf = IsolatedStorageFile.GetUserStoreForApplication())
            //            {
            //                if (fi.Length > isf.AvailableFreeSpace)
            //                {
            //                    MessageBox.Show("I need more free space to process your request." + Environment.NewLine + " Click Increase Space button to apply more free space.");
            //                }
            //                else
            //                {
            //                    using (FileStream sourceStream = fi.OpenRead())
            //                    {
            //                        using (ZipInputStream zipInputStream = new ZipInputStream(sourceStream))
            //                        {
            //                            ZipEntry oneZipEntry;
            //                            while ((oneZipEntry = zipInputStream.GetNextEntry()) != null)
            //                            {
            //                                using (IsolatedStorageFileStream targetXmlStream = isf.CreateFile(targetXmlName))
            //                                {
            //                                    string fileName = System.IO.Path.GetFileName(oneZipEntry.Name);
            //                                    if (!string.IsNullOrEmpty(fileName) && fileName.ToLower().Equals("businessobjects.xml"))
            //                                    {
            //                                        if (zipInputStream.Length > isf.AvailableFreeSpace)
            //                                        {
            //                                            MessageBox.Show("I need more free space to process your request." + Environment.NewLine + " Click Increase Space button to apply more free space.");
            //                                        }
            //                                        else
            //                                        {
            //                                            byte[] buffer = new byte[10240];
            //                                            int count = 0;
            //                                            do
            //                                            {
            //                                                count = zipInputStream.Read(buffer, 0, buffer.Length);
            //                                                if (count > 0)
            //                                                {
            //                                                    targetXmlStream.Write(buffer, 0, count);
            //                                                }
            //                                            } while (count > 0);

            //                                            targetXmlStream.Position = 0;

            //                                            XNamespace xsi = "http://www.w3.org/2001/XMLSchema-instance";
            //                                            XNamespace io = "http://enterprise.businessobjects.com/infoobject";

            //                                            XElement targetRoot = XElement.Load(targetXmlStream);

            //                                            using (IsolatedStorageFileStream sourceXmlStream = isf.OpenFile(sourceXmlName, FileMode.Open))
            //                                            {
            //                                                XElement sourceRoot = XElement.Load(sourceXmlStream);
            //                                                var sourceTypeAndCuid = sourceRoot.Elements().Select(c => new
            //                                                {
            //                                                    Type = c.Attribute(xsi + "type").Value,
            //                                                    Cuid = c.Element(io + "Cuid").Value,
            //                                                    Name = c.Element(io + "Name").Value,
            //                                                    ParentCuid = c.Element(io + "ParentCuid").Value
            //                                                });
            //                                                var targetTypeAndCuid = targetRoot.Elements().Select(c => new
            //                                                {
            //                                                    Type = c.Attribute(xsi + "type").Value,
            //                                                    Cuid = c.Element(io + "Cuid").Value,
            //                                                    Name = c.Element(io + "Name").Value,
            //                                                    ParentCuid = c.Element(io + "ParentCuid").Value
            //                                                });

            //                                                var sameNameDiffID = sourceTypeAndCuid
            //                                                                                .Join(targetTypeAndCuid,
            //                                                                                        c => new { Name = c.Name, ParentCuid = c.ParentCuid },
            //                                                                                        s => new { Name = s.Name, ParentCuid = s.ParentCuid },
            //                                                                                        (c, s) => new { c = c, s = s })
            //                                                                                .Where(c => c.c.Cuid != c.s.Cuid)
            //                                                                                .Select(c => new NameCuidType { Name = c.s.Name, Type = c.s.Type, Cuid = c.s.Cuid, ParentCuid = c.s.ParentCuid })
            //                                                                                .OrderBy(c => c.Name);

            //                                                var sameIDDiffName = sourceTypeAndCuid
            //                                                                                .Join(targetTypeAndCuid,
            //                                                                                        c => new { Name = c.Cuid, ParentCuid = c.ParentCuid },
            //                                                                                        s => new { Name = s.Cuid, ParentCuid = s.ParentCuid },
            //                                                                                    (c, s) => new { c = c, s = s })
            //                                                                                .Where(c => c.c.Name != c.s.Name)
            //                                                                                .Select(c => new NameCuidType { Name = c.s.Name, Type = c.s.Type, Cuid = c.s.Cuid, ParentCuid = c.s.ParentCuid })
            //                                                                                .OrderBy(c => c.Name);
            //                                                //var same = sourceTypeAndCuid
            //                                                //                .Join(targetTypeAndCuid,
            //                                                //                    c => new { Name = c.Name, Cuid = c.Cuid, ParentCuid = c.ParentCuid },
            //                                                //                        s => new { Name = s.Name, Cuid = s.Cuid, ParentCuid = s.ParentCuid },
            //                                                //                    (c, s) => new { c = c, s = s })
            //                                                //                 .Join(sourceTypeAndCuid,
            //                                                //                      r => r.c.ParentCuid,
            //                                                //                      t => t.Cuid,
            //                                                //                      (r, t) => new { r = r, t = t })
            //                                                //                .Select(z => new NameCuidType { Name = z.t.Name + "." + z.r.c.Name, Type = z.r.c.Type, Cuid = z.r.c.Cuid, ParentCuid = z.t.Name })
            //                                                //                .OrderBy(c => c.Name);

            //                                                var onlySource = sourceTypeAndCuid.Select(c => c.Cuid)
            //                                                                       .Except(targetTypeAndCuid.Select(s => s.Cuid))
            //                                                                       .Join(sourceTypeAndCuid, c => c, s => s.Cuid, (c, s) => new { c = c, s = s })
            //                                                                       .Select(c => new NameCuidType { Name = c.s.Name, Type = c.s.Type, Cuid = c.s.Cuid, ParentCuid = c.s.ParentCuid })
            //                                                                       .Select(r => r.Name)
            //                                                                       .Except(sameNameDiffID.Select(t => t.Name))
            //                                                                       .Select(z => new NameCuidType { Name = z })
            //                                                                       .OrderBy(c => c.Name);

            //                                                var onlyTarget = targetTypeAndCuid
            //                                                                        .Select(c => c.Cuid)
            //                                                                        .Except(sourceTypeAndCuid.Select(s => s.Cuid))
            //                                                                        .Join(targetTypeAndCuid, c => c, s => s.Cuid, (c, s) => new { c = c, s = s })
            //                                                                        .Select(c => new NameCuidType { Name = c.s.Name, Type = c.s.Type, Cuid = c.s.Cuid, ParentCuid = c.s.ParentCuid })
            //                                                                   //     .Select(r => r.Name)
            //                                                                      // .Except(sameNameDiffID.Select(t => t.Name))
            //                                                                      // .Select(z => new NameCuidType { Name = z })
            //                                                                       .OrderBy(c => c.Name);

            //                                                dgOnlyInSource.ItemsSource = onlySource.ToList();
            //                                                dgOnlyInTarget.ItemsSource = onlyTarget.ToList();
            //                                                dgSameNameButDiffCuid.ItemsSource = sameNameDiffID.ToList();
            //                                                dgSameCuidButName.ItemsSource = sameIDDiffName.ToList();
            //                                              //  dgIdentical.ItemsSource = same.ToList();
            //                                            }
            //                                        }
            //                                    }
            //                                }
            //                            }
            //                        }
            //                    }
            //                }
            //            }
            //        }
            //    }

        }

        private void Page_Loaded(object sender, RoutedEventArgs e)
        {
            if (this.NavigationContext.QueryString.ContainsKey("SourceXmlFileName"))
                sourceXmlName = this.NavigationContext.QueryString["SourceXmlFileName"];
            else
                sourceXmlName = "businessobjects.xml";

            if (this.NavigationContext.QueryString.ContainsKey("TargetXmlFileName"))
                targetXmlName = this.NavigationContext.QueryString["TargetXmlFileName"];
            else
                targetXmlName = "targetBusinessObjects.xml";

            if (this.NavigationContext.QueryString.ContainsKey("SourceBIARFileName"))
                SourceBIARFileName = this.NavigationContext.QueryString["SourceBIARFileName"];
            else
                SourceBIARFileName = "sourceBusinessObjects.biar";

            if (this.NavigationContext.QueryString.ContainsKey("TargetBIARFileName"))
                TargetBIARFileName = this.NavigationContext.QueryString["TargetBIARFileName"];
            else
                TargetBIARFileName = "targetBusinessObjects.biar";

            //   tbSourceBIARFileName.Text = SourceBIARFileName;
            //   tbTargetBIARFileName.Text = TargetBIARFileName;
            DoComparison();
        }

        private void DoComparison()
        {
            using (IsolatedStorageFile isf = IsolatedStorageFile.GetUserStoreForApplication())
            {
                using (IsolatedStorageFileStream sourceXmlStream = isf.OpenFile(sourceXmlName, FileMode.Open))
                {
                    using (IsolatedStorageFileStream targetXmlStream = isf.OpenFile(targetXmlName, FileMode.Open))
                    {
                        XNamespace xsi = "http://www.w3.org/2001/XMLSchema-instance";
                        XNamespace io = "http://enterprise.businessobjects.com/infoobject";

                        XElement targetRoot = XElement.Load(targetXmlStream);

                        XElement sourceRoot = XElement.Load(sourceXmlStream);

                        IEnumerable<NameCuidType> sourceTypeAndCuid = sourceRoot.Elements().Select(
                            c => new NameCuidType
                            {
                                Type = c.Attribute(xsi + "type").Value,
                                Cuid = c.Element(io + "Cuid").Value,
                                Name = c.Element(io + "Name").Value,
                                ParentCuid = c.Element(io + "ParentCuid").Value
                            });

                        IEnumerable<NameCuidType> targetTypeAndCuid = targetRoot.Elements().Select(
                            c => new NameCuidType
                            {
                                Type = c.Attribute(xsi + "type").Value,
                                Cuid = c.Element(io + "Cuid").Value,
                                Name = c.Element(io + "Name").Value,
                                ParentCuid = c.Element(io + "ParentCuid").Value
                            });

                        IEnumerable<NameCuidType> sameNameDiffID = sourceTypeAndCuid
                                                        .Join(targetTypeAndCuid,
                                                                c => c,
                                                                s => s,
                                                                (c, s) => new { c = c, s = s },
                                                                new NameParentCuidComparer())
                                                        .Where(c => c.c.Cuid != c.s.Cuid)
                                                        .Select(c => new NameCuidType { Name = c.s.Name, Type = c.s.Type, Cuid = c.s.Cuid, ParentCuid = c.s.ParentCuid })
                                                        .OrderBy(c => c.Name);


                        IEnumerable<NameCuidType> sameIDDiffName = sourceTypeAndCuid
                                                        .Join(targetTypeAndCuid,
                                                                c => c,
                                                                s => s,
                                                            (c, s) => new { c = c, s = s },
                                                            new CuidComparer())
                                                        .Where(c => c.c.Name != c.s.Name)
                                                        .Select(c => new NameCuidType { Name = c.s.Name, Type = c.s.Type, Cuid = c.s.Cuid, ParentCuid = c.s.ParentCuid })
                                                        .OrderBy(c => c.Name);

                        //IEnumerable<NameCuidType> same = sourceTypeAndCuid
                        //                .Join(targetTypeAndCuid,
                        //                    c => new { Name = c.Name, Cuid = c.Cuid, ParentCuid = c.ParentCuid },
                        //                        s => new { Name = s.Name, Cuid = s.Cuid, ParentCuid = s.ParentCuid },
                        //                    (c, s) => new { c = c, s = s })
                        //                 .Join(sourceTypeAndCuid,
                        //                      r => r.c.ParentCuid,
                        //                      t => t.Cuid,
                        //                      (r, t) => new { r = r, t = t })
                        //                .Select(z => new NameCuidType { Name = z.t.Name + "." + z.r.c.Name, Type = z.r.c.Type, Cuid = z.r.c.Cuid, ParentCuid = z.t.Name })
                        //                .OrderBy(c => c.Name);

                        //var onlySource = sourceTypeAndCuid
                        //                       .Select(c => c.Cuid)
                        //                       .Except(targetTypeAndCuid.Select(s => s.Cuid))
                        //                       .Join(sourceTypeAndCuid, c => c, s => s.Cuid, (c, s) => new { c = c, s = s })
                        //                       .Select(c => new NameCuidType { Name = c.s.Name, Type = c.s.Type, Cuid = c.s.Cuid, ParentCuid = c.s.ParentCuid })
                        //                       .Select(r => r.Name)
                        //                       .Except(sameNameDiffID.Select(t => t.Name))
                        //                       .Select(z => new NameCuidType { Name = z })
                        //                       .OrderBy(c => c.Name);

                        IEnumerable<NameCuidType> onlySource = sourceTypeAndCuid
                                                   .Except(targetTypeAndCuid, new CuidComparer())
                                                   .Except(sameNameDiffID, new NameComparer())
                                                   .OrderBy(c => c.Name);

                        IEnumerable<NameCuidType> onlyTarget = targetTypeAndCuid
                                                    .Except(sourceTypeAndCuid, new CuidComparer())
                                                    .Except(sameNameDiffID, new NameComparer())
                                                    .OrderBy(c => c.Name);

                        //targetTypeAndCuid
                        //                    .Select(c => c.Cuid)
                        //                    .Except(sourceTypeAndCuid.Select(s => s.Cuid))
                        //                    .Join(targetTypeAndCuid, c => c, s => s.Cuid, (c, s) => new { c = c, s = s })
                        //                    .Select(c => new NameCuidType { Name = c.s.Name, Type = c.s.Type, Cuid = c.s.Cuid, ParentCuid = c.s.ParentCuid })
                        //                    .Select(r => r.Name)
                        //                    .Except(sameNameDiffID.Select(t => t.Name))
                        //                    .Select(z => new NameCuidType { Name = z })
                        //                    .OrderBy(c => c.Name);

                        NewObjectNumber = onlySource.Count();
                        OnlyInDestinationNumber = onlyTarget.Count();
                        SameNameDiffIDNumber = sameNameDiffID.Count();
                        SameIDDiffNameNumber = sameIDDiffName.Count();

                        dgOnlyInSource.ItemsSource = onlySource;
                        dgOnlyInTarget.ItemsSource = onlyTarget;
                        dgSameNameButDiffCuid.ItemsSource = sameNameDiffID;
                        dgSameCuidButName.ItemsSource = sameIDDiffName;
                        //     dgIdentical.ItemsSource = same.ToList();
                    }
                }
            }
        }

        private void showComparisonDetail_Click(object sender, RoutedEventArgs e)
        {
            Button tmp = sender as Button;
            if (tmp.Tag.ToString().Equals("0"))
            {
                GridLength tmpHeight = LayoutRoot.RowDefinitions[2].Height;
                LayoutRoot.RowDefinitions[2].Height = new GridLength(1);
                LayoutRoot.RowDefinitions[3].Height = tmpHeight;

                tmp.Tag = 1;
                tmp.Content = "Show Summary Comparison Result";
            }
            else
            {
                GridLength tmpHeight = LayoutRoot.RowDefinitions[3].Height;
                LayoutRoot.RowDefinitions[3].Height = new GridLength(1);
                LayoutRoot.RowDefinitions[2].Height = tmpHeight;
                tmp.Tag = 0;
                tmp.Content = "Show Detail Comparison Result";
            }


        }
    }
}
